package com.laomuji.android.mvvm.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Path
import android.graphics.RectF
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.widget.LinearLayout
import com.laomuji.android.mvvm.R

/**
 * 封装常用ui功能的 LinearLayout
 * 1. 圆角背景
 * 2. 圆角边框
 * 3. 区域裁剪
 * 4. 渐变背景色.
 * 如果需要动态修改属性,需要调用[RoundBorderLinearLayout.postInvalidate].
 * @author laomuji666
 * @since 2024/2/21
 */
class RoundBorderLinearLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) :
    LinearLayout(context, attrs) {
    private var contentColor = 0
    private var contentEndColor = 0
    private var radiusTopStart = 0
    private var radiusTopEnd = 0
    private var radiusBottomEnd = 0
    private var radiusBottomStart = 0
    private var borderColor = 0
    private var borderWidth = 0
    private var forceClip = false
    private var gradientOrientation = 0
    private val contentBackgroundRectF = RectF()
    private val path = Path()

    init {
        // 强制开启绘制,确保onDraw会被调用.
        setWillNotDraw(false)

        if (attrs != null) {
            initAttr(context, attrs)
        }
    }

    private fun initAttr(context: Context, attrs: AttributeSet) {
        context.obtainStyledAttributes(attrs, R.styleable.RoundBorderLinearLayout)
            .use { typedArray ->
                contentColor = typedArray.getColor(
                    R.styleable.RoundBorderLinearLayout_rbllContentColor,
                    Color.TRANSPARENT
                )
                contentEndColor = typedArray.getColor(
                    R.styleable.RoundBorderLinearLayout_rbllContentEndColor,
                    contentColor
                )
                gradientOrientation = typedArray.getInt(
                    R.styleable.RoundBorderLinearLayout_rbllGradientOrientation,
                    0
                )
                val radius = typedArray.getDimensionPixelSize(
                    R.styleable.RoundBorderLinearLayout_rbllRadius,
                    0
                )
                radiusTopStart = typedArray.getDimensionPixelSize(
                    R.styleable.RoundBorderLinearLayout_rbllRadiusTopStart, radius
                )
                radiusTopEnd = typedArray.getDimensionPixelSize(
                    R.styleable.RoundBorderLinearLayout_rbllRadiusTopEnd, radius
                )
                radiusBottomEnd = typedArray.getDimensionPixelSize(
                    R.styleable.RoundBorderLinearLayout_rbllRadiusBottomEnd, radius
                )
                radiusBottomStart = typedArray.getDimensionPixelSize(
                    R.styleable.RoundBorderLinearLayout_rbllRadiusBottomStart, radius
                )
                borderColor = typedArray.getColor(
                    R.styleable.RoundBorderLinearLayout_rbllBorderColor, Color.TRANSPARENT
                )
                borderWidth = typedArray.getDimensionPixelSize(
                    R.styleable.RoundBorderLinearLayout_rbllBorderWidth, 0
                )
                forceClip = typedArray.getBoolean(
                    R.styleable.RoundBorderLinearLayout_rbllForceClip, false
                )
            }
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        // 更新绘制位置
        initRect()
    }

    public override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        // 绘制背景
        background = createRadiusShape()
    }

    override fun dispatchDraw(canvas: Canvas) {
        //不需要裁剪区域
        if (!forceClip) {
            super.dispatchDraw(canvas)
            return
        }

        //限制绘制区域只允许在path中
        canvas.save()
        canvas.clipPath(path)
        super.dispatchDraw(canvas)
        canvas.restore()
    }

    private val isRtL: Boolean
        /**
         * 是否是从右往左布局
         */
        get() = layoutDirection == LAYOUT_DIRECTION_RTL

    /**
     * 初始化矩形区域
     */
    private fun initRect() {
        contentBackgroundRectF.left = (0.5f * borderWidth)
        contentBackgroundRectF.top = (0.5f * borderWidth)
        contentBackgroundRectF.right = measuredWidth - contentBackgroundRectF.left
        contentBackgroundRectF.bottom = measuredHeight - contentBackgroundRectF.top

        if (forceClip) {
            path.reset()
            path.addRoundRect(
                contentBackgroundRectF,
                radii,
                Path.Direction.CW
            )
            path.close()
        }
    }

    /**
     * 创建有角度的矩形
     */
    private fun createRadiusShape(): GradientDrawable {
        val drawable = GradientDrawable()
        drawable.cornerRadii = radii
        drawable.colors = intArrayOf(contentColor, contentEndColor)
        if (gradientOrientation == 0) {
            drawable.setColor(contentColor)
        } else {
            drawable.orientation = drawableOrientation
        }
        drawable.setStroke(borderWidth, borderColor)
        drawable.setBounds(
            contentBackgroundRectF.left.toInt(),
            contentBackgroundRectF.top.toInt(),
            contentBackgroundRectF.right.toInt(),
            contentBackgroundRectF.bottom.toInt()
        )
        return drawable
    }

    private val drawableOrientation: GradientDrawable.Orientation
        /**
         * 获取渐变方向,支持RTL
         */
        get() {
            var drawableOrientation = GradientDrawable.Orientation.LEFT_RIGHT
            if (gradientOrientation == 1) {
                drawableOrientation = GradientDrawable.Orientation.TOP_BOTTOM
            } else if (gradientOrientation == 2) {
                drawableOrientation =
                    if (isRtL) GradientDrawable.Orientation.TR_BL else GradientDrawable.Orientation.TL_BR
            } else if (gradientOrientation == 3) {
                drawableOrientation =
                    if (isRtL) GradientDrawable.Orientation.RIGHT_LEFT else GradientDrawable.Orientation.LEFT_RIGHT
            } else if (gradientOrientation == 4) {
                drawableOrientation =
                    if (isRtL) GradientDrawable.Orientation.TL_BR else GradientDrawable.Orientation.TR_BL
            }
            return drawableOrientation
        }

    private val radii: FloatArray
        /**
         * 获取圆角数组,支持RTL
         */
        get() {
            val radii = floatArrayOf(
                radiusTopStart.toFloat(), radiusTopStart.toFloat(),
                radiusTopEnd.toFloat(), radiusTopEnd.toFloat(),
                radiusBottomEnd.toFloat(), radiusBottomEnd.toFloat(),
                radiusBottomStart.toFloat(), radiusBottomStart.toFloat()
            )
            if (isRtL) {
                var temp = radii[0]
                radii[0] = radii[2]
                radii[2] = temp
                temp = radii[1]
                radii[1] = radii[3]
                radii[3] = temp
                temp = radii[4]
                radii[4] = radii[6]
                radii[6] = temp
                temp = radii[5]
                radii[5] = radii[7]
                radii[7] = temp
            }
            return radii
        }

    fun setBorderColor(color: Int) {
        borderColor = color
        postInvalidate()
    }

    fun setBorderWidth(width: Int) {
        borderWidth = width
        postInvalidate()
    }

    override fun postInvalidate() {
        super.postInvalidate()
        forceLayout()
        requestLayout()
    }
}